package cn.seaboot.admin.security.login;

import cn.seaboot.admin.logger.service.LoginLogService;
import cn.seaboot.admin.mvc.Result;
import cn.seaboot.admin.mvc.utils.IpUtils;
import cn.seaboot.admin.security.jwt.AuthenticationJwt;
import cn.seaboot.admin.security.jwt.SecurityJwtProperties;
import cn.seaboot.commons.file.ResponseWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 认证成功回调，登录成功，写回JWT
 * 这个类无法用注入的方式进行初始化，需要手动调用
 *
 * @author Mr.css
 * @version 2021-12-23 11:59
 */
@Configuration
public class LoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
    private final Logger logger = LoggerFactory.getLogger(LoginSuccessHandler.class);

    /**
     * 令牌执行对象
     */
    @Resource
    private AuthenticationJwt authenticationJwt;

    /**
     * 参数配置
     */
    @Resource
    private SecurityJwtProperties securityJwtProperties;

    @Resource
    private LoginLogService loginLogService;

    /**
     * Called when a user has been successfully authenticated.
     * 认证成功之后调用，生成 token
     *
     * @param request        -
     * @param response       -
     * @param authentication 认证信息
     * @throws IOException -from write
     */
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
        String token = authenticationJwt.encrypt(authentication);

        // 将用户令牌，缓存到会话中
        if (securityJwtProperties.isUsingSession()) {
            request.getSession().setAttribute(securityJwtProperties.getTokenName(), token);
        }

        // 账户以及登录终端的一些信息
        try {
            String ip = IpUtils.getIpAddress(request);
            String agent = request.getHeader("user-agent");
            String account = request.getParameter(LoginFilter.USERNAME_FIELD);
            // 上下文设计不方便拿到用户 ID，账户也有唯一属性，这里直接置空
            loginLogService.insert(LoginFilter.CHANNEL_NAME, null,  account, token, ip, agent, LoginStatus.SUCCEED);
        } catch (Exception e) {
            logger.error("login log failed: ", e);
        }
        ResponseWriter.writeJson(response, Result.succeed(token));
    }

    public AuthenticationJwt getAuthenticationJwt() {
        return authenticationJwt;
    }

    public void setAuthenticationJwt(AuthenticationJwt authenticationJwt) {
        this.authenticationJwt = authenticationJwt;
    }

    public SecurityJwtProperties getSecurityJwtProperties() {
        return securityJwtProperties;
    }

    public void setSecurityJwtProperties(SecurityJwtProperties securityJwtProperties) {
        this.securityJwtProperties = securityJwtProperties;
    }
}
